#include "../common/dispatcher.hpp"
#include "../client/rpc_client.hpp"
#include "rpc_router.hpp"
#include "rpc_registry.hpp"
#include "rpc_topic.hpp"

namespace zl
{
    namespace server
    {
        // 注册中心服务端：只需要针对服务注册与发现请求进行处理即可
        class RegistryServer
        {
        public:
            using ptr = std::shared_ptr<RegistryServer>;

            RegistryServer(int port) : _pd_manager(std::make_shared<PDManager>()),
                                       _dispatcher(std::make_shared<zl::Dispatcher>())
            {
                auto service_cb = std::bind(&PDManager::onServiceRequest, _pd_manager.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<ServiceRequest>(MType::REQ_SERVICE, service_cb);

                _server = zl::ServerFactory::create(port);
                auto message_cb = std::bind(&zl::Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);

                auto close_cb = std::bind(&RegistryServer::onconnShutdown, this, std::placeholders::_1);
                _server->setCloseCallback(close_cb);
            }

            void start()
            {
                _server->start();
            }

        private:
            void onconnShutdown(const BaseConnection::ptr &conn)
            {
                _pd_manager->onConnShutdown(conn);
            }

        private:
            PDManager::ptr _pd_manager;
            Dispatcher::ptr _dispatcher;
            zl::BaserServer::ptr _server;
        };

        class RpcServer
        {
        public:
            using ptr = std::shared_ptr<RpcServer>;

            RpcServer(const Address &access_addr,
                      bool enableRegistry = false,
                      const Address &registry_server_addr = Address()) : _enableRegistry(enableRegistry),
                                                                         _access_addr(access_addr),
                                                                         _router(std::make_shared<zl::server::RpcRouter>()),
                                                                         _dispatcher(std::make_shared<zl::Dispatcher>())
            {
                if (_enableRegistry)
                {
                    _registry_client = std::make_shared<client::RegistryClient>(registry_server_addr.first, registry_server_addr.second);
                }
                // 当前成员server是一个rpcserver，用于提供rpc服务的
                auto rpc_cb = std::bind(&RpcRouter::onRpcRequest, _router.get(), std::placeholders::_1, std::placeholders::_2);
                _dispatcher->registerHandler<zl::RpcRequest>(MType::REQ_RPC, rpc_cb);

                _server = zl::ServerFactory::create(_access_addr.second);
                auto message_cb = std::bind(&zl::Dispatcher::onMessage, _dispatcher.get(), std::placeholders::_1, std::placeholders::_2);
                _server->setMessageCallback(message_cb);
            }

            void registerMethod(const ServiceDescribe::ptr &sd)
            {
                if (_enableRegistry)
                {
                    _registry_client->registerMethod(sd->method(), _access_addr);
                }
                _router->registerMethod(sd);
            }

            void start()
            {
                _server->start();
            }

        private:
            bool _enableRegistry;
            Address _access_addr;
            client::RegistryClient::ptr _registry_client;
            RpcRouter::ptr _router;
            Dispatcher::ptr _dispatcher;
            zl::BaserServer::ptr _server;
        };

        class TopicServer {
            public:
                using ptr = std::shared_ptr<TopicServer>;
                TopicServer(int port):
                    _topic_manager(std::make_shared<TopicManager>()),
                    _dispatcher(std::make_shared<zl::Dispatcher>())
                {
                    auto topic_cb = std::bind(&TopicManager::onTopicRequest, _topic_manager.get(),
                        std::placeholders::_1, std::placeholders::_2);
                    _dispatcher->registerHandler<TopicRequest>(MType::REQ_TOPIC, topic_cb);

                    _server = zl::ServerFactory::create(port);
                    auto message_cb = std::bind(&zl::Dispatcher::onMessage, _dispatcher.get(), 
                        std::placeholders::_1, std::placeholders::_2);
                    _server->setMessageCallback(message_cb);

                    auto close_cb = std::bind(&TopicServer::onConnShutdown, this, std::placeholders::_1);
                    _server->setCloseCallback(close_cb);
                }
                void start() {
                    _server->start();
                }
            private:
                void onConnShutdown(const BaseConnection::ptr &conn) {
                    _topic_manager->onShutdown(conn);
                }
            private:
                TopicManager::ptr _topic_manager;
                Dispatcher::ptr _dispatcher;
                BaserServer::ptr _server;
        };

    }
}